package com.WaVel.controller.admin;

import com.Emplyment.context.BaseContext;
import com.Emplyment.dto.ArticleDto;
import com.Emplyment.dto.ArticlePageQueryDto;
import com.Emplyment.entity.Article;
import com.Emplyment.exception.RegisterException;
import com.Emplyment.result.PageResult;
import com.Emplyment.result.Result;
import com.Emplyment.util.CacheHotCompany;
import com.WaVel.service.ArticleService;
import com.WaVel.task.CompanyTask;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
@RequestMapping("/article")
public class ArticleController {


    @Autowired
    private ArticleService articleService;
//    @Autowired
//    private RedissonClient redissonClient;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private CompanyTask companyTask;
    @Autowired
    private ObjectMapper objectMapper;

    private final String exchangeName = "itcast.direct";

    private static final String companyHASH_KEY = "company:HASH:data";

    private static final String COMPANY_HOT_DATA = "company:ZSET:rank";

    private static final String Message_Add_Exchange = "company.add";

    private static final String Message_Update_Exchange = "company.update";

    private static final String Message_Delete_Exchange = "company.delete";

    //公司列表分页
    @PostMapping("/manage")
    public Result<PageResult> page(@RequestBody ArticlePageQueryDto dto){

        log.info("公司详情分列表分页结果为:{}",dto);
        PageResult pageResult = articleService.page(dto);
        log.info("公司详情分页结果为:{}",pageResult);
        return Result.success(pageResult);
    }



    /**
     * 添加公司数据
     * @param dto
     */
    @PostMapping
    @Transactional
    public Result saveEmplyee(@RequestBody ArticleDto dto) throws IOException {
        log.info("添加公司数据:{}",dto);
        //将数据添加进入数据库
        Article article = articleService.saveEmplyment(dto);
        String Emplyment = JSON.toJSONString(article);
        long expireTime = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(2);
        CacheHotCompany cacheHotCompany = new CacheHotCompany();
        cacheHotCompany.setCompany(article);
        cacheHotCompany.setExpireAt(expireTime);

        String jsonData = objectMapper.writeValueAsString(cacheHotCompany);

//        //创建布隆过滤器
//        RBloomFilter<String> bloomFilter = redissonClient.getBloomFilter("Emplyment-name");
//        //第一个参数表示大小 预期插入数量，第二个参数表示错误概率，错误概率不能大于 1，错误概率不能为负
//        bloomFilter.tryInit(10000,0.03);
        //把id放入布隆过滤器
//        bloomFilter.add("Emplyment"+article.getId());

        //将数据存入redis的hash表中
        redisTemplate.opsForHash().put(companyHASH_KEY, article.getId().toString(), jsonData);

        //将数据异步到el数据库当中
        rabbitTemplate.convertAndSend(exchangeName,Message_Add_Exchange,Emplyment);
        return Result.success();
    }

    @PutMapping
    @Transactional
    public Result updateEmplyee(@RequestBody ArticleDto dto) throws IOException {
        //将数据更新进入数据库
        log.info("更新公司数据:{}",dto);
        try {
            //延时双删
//            redisTemplate.opsForHash().delete(companyHASH_KEY, dto.getId().toString());
            Article article = articleService.updateEmplyment(dto);
            long expireTime = System.currentTimeMillis() + TimeUnit.HOURS.toMillis(2);
            CacheHotCompany cacheHotCompany = new CacheHotCompany();
            cacheHotCompany.setCompany(article);
            cacheHotCompany.setExpireAt(expireTime);

            String jsonData = objectMapper.writeValueAsString(cacheHotCompany);

            if(redisTemplate.opsForHash().get(companyHASH_KEY, dto.getId().toString())!= null){
                redisTemplate.opsForHash().put(companyHASH_KEY, dto.getId().toString(), jsonData);
            }

            String emplyment = objectMapper.writeValueAsString(article);
            //将数据异步到el数据库当中
            rabbitTemplate.convertAndSend(exchangeName,Message_Update_Exchange,emplyment);

        } catch (Exception e) {
            log.error("更新公司数据失败:{}",e);
        }
        return Result.success();
    }

    /**
     * 删除公司数据
     */
    @DeleteMapping("/{articleId}")
    @Transactional
    public Result deleteEmplyee(@PathVariable("articleId") Long id) {
        log.info("删除公司数据:{}",id);

        //延时双删
        redisTemplate.opsForHash().delete(companyHASH_KEY, id.toString());

        articleService.deleteEmplyment(id);
        //延时双删：异步执行第二次删除（延迟 1 秒）
            CompletableFuture.runAsync(() -> {
                try {
                    TimeUnit.MILLISECONDS.sleep(1000); // 延时 1 秒
                    redisTemplate.opsForHash().delete(companyHASH_KEY, id.toString());
                    log.info("延时双删完成，ID: {}", id);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    log.error("延时双删被中断", e);
                } catch (Exception e) {
                    log.error("延时双删失败", e);
                }
            });

        Double score = redisTemplate.opsForZSet().score(COMPANY_HOT_DATA, id.toString());
        //将数据异步到el数据库当中
        rabbitTemplate.convertAndSend(exchangeName,Message_Delete_Exchange,id.toString());
        if (score != null) {
            companyTask.processCompanyData();
        }

        return Result.success();
    }

}
